package be.neo4reactome.starter;

import be.neo4reactome.importer.Importer;
import be.neo4reactome.queries.CypherQuery;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.kernel.impl.util.FileUtils;

import java.io.File;
import java.io.IOException;

public class Neo4reactome {

    public static final String INTERACTIONS_PATH = "data/homo_sapiens.interactions_reduced.txt";
    public static final String PATHWAYS_PATH = "data/curated_uniprot_2_pathways_reduced.txt";

    private GraphDatabaseService graphDb;

    /**
     * Starts an existing database.
     * @param dbPath Database path
     */
    public Neo4reactome(String dbPath) {
        this(dbPath, false);
    }

    /**
     * Constructor for starting a new neo4reactome database.
     * @param dbPath Database path.
     * @param cleanStart Condition whether to clear the database previously.
     */
    public Neo4reactome(String dbPath, boolean cleanStart) {
        // Clear the database.
        if(cleanStart) clearDatabase(dbPath);

        // Start the database.
        startDatabase(dbPath);
    }

    /**
	 * Start the database.
     * @param dbPath Database path
	 */
	public void startDatabase(String dbPath) {
		graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(dbPath);
        // graphDb = new RestGraphDatabase("http://localhost:7474/db/data");
		registerShutdownHook(graphDb);
	}

    /**
     * Returns the graph database.
     * @return graphDb
     */
    public GraphDatabaseService getGraphDatabase(){
        return graphDb;
    }

	/**
	 * Registers a shutdown hook for the Neo4j instance so that it shuts down nicely when the VM exits.
	 * 
	 * @param graphDb GraphDatabaseService
	 */
	private static void registerShutdownHook(final GraphDatabaseService graphDb) {
		// 
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				graphDb.shutdown();
			}
		});
	}

    /**
     * Clears the database.
     * @param dbPath Database path.
     */
	private void clearDatabase(String dbPath) {
		try {
			FileUtils.deleteRecursively(new File(dbPath));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * Shuts down the graph database.
	 */
	public void shutDown() {
		System.out.println();
		System.out.println("Shutting down database ...");
		// Shutdown the server.
		graphDb.shutdown();
	}


	
	public static void main(String[] args) {

		// Init Neo4reactome.
		Neo4reactome neo4reactome = new Neo4reactome("target/neo4reactome", true);

		// Import the data
        new Importer(neo4reactome.graphDb, INTERACTIONS_PATH, PATHWAYS_PATH);

        final CypherQuery query = new CypherQuery(neo4reactome.graphDb);
        CypherQuery.printResult("Get first node",query.getFirstNode(), "n");

        CypherQuery.printResult("Get all nodes",query.getAllNodes(), "n");

        CypherQuery.printResult("Get particular node P69905",query.getProteinByAccession("P69905"), "protein");

        CypherQuery.printRelationship("Get relationships", query.getRelationshipsFromProtein(), "rel");

        CypherQuery.printResult("Get direct complex proteins: HBA to HBB", query.getInteractionProteins("P69905", Importer.InteractionType.INDIRECT_COMPLEX), "proteinB");

        CypherQuery.printResult("Get all proteins for particular pathway",query.getAllProteinsForPathway("Immune System"), "protein");

        CypherQuery.printResult("Get all pathways for particular protein: HBB",query.getAllPathwaysForProtein("P68871"), "pathway");

        CypherQuery.printResult("Get common pathways",query.getAllPathwaysForProteins("P69905", "P68871"), "pathway");

        CypherQuery.printResult("Get shared proteins",query.getSharedInteractionProteins("P69905", "P68871"), "proteinC");

        CypherQuery.printResult("Get similar reactions",query.getSimilarInteractionProteins(1,100),"proteinA");

        System.out.println("Get proteins in the path");
        System.out.println(query.getAllNodesOnPath("P01375", "Q13490").toString());

		// Shutdown the database.
		neo4reactome.shutDown();
		
	}


}
